package com.ddwl.user.service;

import com.ddwl.common.constant.BaseEnum;
import com.ddwl.common.exception.ParamException;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.common.util.UUIDGenerator;
import com.ddwl.schema.bo.user.QueryUserLevelBo;
import com.ddwl.schema.bo.user.UserLevelBo;
import com.ddwl.common.constant.DistConstant;
import com.ddwl.schema.util.DateUtil;
import com.ddwl.schema.vo.dist.DistrConfigVo;
import com.ddwl.schema.vo.dist.UserInviteCountVo;
import com.ddwl.schema.vo.user.UserLevelVo;
import com.ddwl.schema.vo.user.UserVo;
import com.ddwl.user.dao.UserDao;
import com.ddwl.user.dao.UserLevelDao;
import com.ddwl.user.dao.model.User;
import com.ddwl.user.dao.model.UserLevel;
import com.ddwl.user.dao.dto.UserInviteCountQueryDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户等级service
 * @author wenbin
 */
@Slf4j
@Service
public class UserLevelService {

    @Resource
    private UserLevelDao userLevelDao;
    @Resource
    private DistrConfigServer distrConfigServer;
    @Resource
    private UserService userService;
    @Resource
    private UserDistService userDistService;
    @Resource
    private UserDao userDao;



    /**
     *新建用户等级
     */
    @Transactional(rollbackFor = Throwable.class)
    public void saveUserLevel(UserLevelBo bo) {
        ParamException.isNotNull(bo.getId(),"id不为空");
        ParamException.isBlank(bo.getUserLevelName(),"等级名称为空");
        ParamException.isNull(bo.getUserLevelCode(),"对应等级不能为空");
        ParamException.isNull(bo.getDistRate(),"分润比例不能为空");
        //分润比例不能超过直接上级最高比例
        DistrConfigVo distrConfig = distrConfigServer.getDistrConfig(DistConstant.DistrConfigType.PRODUCT.getCode());
        ParamException.isTrue(distrConfig.getTwoAgentRate().compareTo(bo.getDistRate())<0,"分润比例不能超过间接上级比例");

        //校验重复
        checkUserLevel(bo);

        //目前只有邀请好友升级,只需判断人数就可以,不排除后续添加可能
        // 升级要求 0.邀请人数
        bo.setLevelUpReq(0);
        if (bo.getLevelUpReq()!=null&&bo.getLevelUpReq()==0){
            ParamException.isTrue(bo.getLevelUpPeople()==null||bo.getLevelUpPeople()==0,"邀请人数不能为空");
        }
        UserLevel userLevel = BeanConverUtils.convertBean(bo, UserLevel.class);
        userLevel.setId(UUIDGenerator.getShortUUID());
        userLevel.setIsSystem(0);
        userLevelDao.insert(userLevel);
    }

    /**
     *更新用户等级
     */
    @Transactional(rollbackFor = Throwable.class)
    public void updateUserLevel(UserLevelBo bo) {
        ParamException.isBlank(bo.getId(),"id为空");
        bo.setUserLevelCode(null);
        //重复校验
        checkUserLevel(bo);
        //系统默认邀请人数,等级编码不能修改
        UserLevel userLevel = userLevelDao.selectByPrimaryKey(bo.getId());
        ParamException.isTrue(userLevel.getIsSystem()==1
                &&(bo.getUserLevelCode()!=null||bo.getLevelUpPeople()!=null),"系统默认等级邀请人数,等级编码不能修改");
        //分润比例不能超过直接上级最高比例
        if (bo.getDistRate()!=null){
            DistrConfigVo distrConfig = distrConfigServer.getDistrConfig(DistConstant.DistrConfigType.PRODUCT.getCode());
            ParamException.isTrue(distrConfig.getTwoAgentRate().compareTo(bo.getDistRate())<0,"分润比例不能超过直接上级比例");
        }

        UserLevel userLevel1 = BeanConverUtils.convertBean(bo, UserLevel.class);
        userLevelDao.updateByPrimaryKeySelective(userLevel1);
    }

    /**
     *删除用户等级
     */
    public void delete(String id,String userId) {
        ParamException.isBlank(id,"id为空");
        //系统默认等级无法删除
        UserLevel userLevel = userLevelDao.selectByPrimaryKey(id);
        ParamException.isTrue(userLevel.getIsSystem()==1,"系统默认等级不能删除");

        UserLevel userLevel1 = new UserLevel();
        userLevel1.setId(id);
        userLevel1.setModifiedUserId(userId);
        userLevel1.setGmtModified(Instant.now());
        userLevel1.setDflag(BaseEnum.DflagEnum.DELETED.getCode());
        userLevelDao.updateByPrimaryKeySelective(userLevel1);
    }

    /**
     *获取用户等级列表
     */
    public List<UserLevelVo> getList(QueryUserLevelBo bo) {
        List<UserLevelVo> userLevels = userLevelDao.queryUserLevelList(bo);
        return userLevels;
    }

    /**
     *获取用户下一等级列表
     */
    public List<UserLevelVo> getNextLevel(String userId) {

        UserInviteCountQueryDto bo1=new UserInviteCountQueryDto();
        bo1.setUserId(userId);
        //查询累计用户邀请人数
        UserInviteCountVo userInviteCountVoNew = userDistService.queryUserInviteCountNew(bo1);
        bo1.setStartTime(DateUtil.getTimesMorning());
        bo1.setEndTime(Instant.now());
        //查询今天用户邀请人数
        UserInviteCountVo userInviteCountVo = userDistService.queryUserInviteCountNew(bo1);
        bo1.setStartTime(DateUtil.getTimesMorning(-1));
        bo1.setEndTime(DateUtil.getTimesNight(-1));
        //查询昨天用户邀请人数
        UserInviteCountVo userInviteCountVo2 = userDistService.queryUserInviteCountNew(bo1);


        //查询当前等级信息
        UserVo userVo = userService.getById(userId);
        QueryUserLevelBo bo=new QueryUserLevelBo();
        bo.setId(userVo.getUserLevelId());
        UserLevelVo userLevelVo = getList(bo).get(0);

        //查询用户当前等级及下一等级信息
        List<UserLevelVo> userLevels = userLevelDao.getNextLevel(userLevelVo.getUserLevelCode());
        userLevels.get(0).setTodayDist(userInviteCountVo.getDistTotal()==null?0:userInviteCountVo.getDistTotal());
        userLevels.get(0).setTotalDist(userInviteCountVoNew.getDistTotal()==null?0:userInviteCountVoNew.getDistTotal());
        userLevels.get(0).setYesterdayDist(userInviteCountVo2.getDistTotal()==null?0:userInviteCountVo2.getDistTotal());
        return userLevels;
    }

    public UserLevelVo getByUserLevelCode(Integer code){
        UserLevel ul = new UserLevel();
        ul.setUserLevelCode(code);
        return BeanConverUtils.convertBean(userLevelDao.selectOne(ul),UserLevelVo.class);
    }

    /**
     *校验字段不重复
     */
    public void checkUserLevel(UserLevelBo bo){
        List<UserLevel> userLevels = userLevelDao.selectAll();
        if (userLevels!=null&&userLevels.size()!=0){
            //更新
            if (bo.getId()!=null){
                //用户等级名称
                if (!StringUtils.hasText(bo.getUserLevelName())){
                    List<UserLevel> collect = userLevels.stream().filter(o ->
                            o.getUserLevelName().equals(bo.getUserLevelName())&&(!o.getId().equals(bo.getId()))
                    ).collect(Collectors.toList());
                    ParamException.isTrue(collect!=null&&collect.size()!=0,"用户等级名称重复");
                }
                //用户等级编码
                if (bo.getUserLevelCode()!=null){
                    List<UserLevel> collect = userLevels.stream().filter(o ->
                            o.getUserLevelCode()==bo.getUserLevelCode()&&(!o.getId().equals(bo.getId()))
                    ).collect(Collectors.toList());
                    ParamException.isTrue(collect!=null&&collect.size()!=0,"用户等级编码重复");
                }
            }else{
                //新增
                //用户等级名称
                if (!StringUtils.hasText(bo.getUserLevelName())){
                    List<UserLevel> collect = userLevels.stream().filter(o ->
                            o.getUserLevelName().equals(bo.getUserLevelName())
                    ).collect(Collectors.toList());
                    ParamException.isTrue(collect!=null&&collect.size()!=0,"用户等级名称重复");
                }
                //用户等级编码
                if (bo.getUserLevelCode()!=null){
                    List<UserLevel> collect = userLevels.stream().filter(o ->
                            o.getUserLevelCode()==bo.getUserLevelCode()
                    ).collect(Collectors.toList());
                    ParamException.isTrue(collect!=null&&collect.size()!=0,"用户等级编码重复");
                }
            }

        }
    }

    /**
     * 订正用户等级数据任务
     **/
    public void correctUserLevel() {
        List<String> ids = userDao.selectAll().stream().map(User::getId).collect(Collectors.toList());
        UserInviteCountQueryDto bo=new UserInviteCountQueryDto();
        bo.setUserIds(ids);
        List<UserInviteCountVo> userInviteCountVoList = userDistService.queryUserInviteCountAll(bo);
        List<UserLevelVo> levelVos = getList(new QueryUserLevelBo()).stream()
                .sorted(Comparator.comparing(UserLevelVo::getUserLevelCode).reversed()).collect(Collectors.toList());

        List<User> users=new ArrayList<>();

        for (UserInviteCountVo userInviteCountVo: userInviteCountVoList) {
            for (UserLevelVo o:levelVos) {
                if ((userInviteCountVo.getDistTotal()==null?0:userInviteCountVo.getDistTotal())>=o.getLevelUpPeople()){
                    User user=new User();
                    user.setId(userInviteCountVo.getId());
                    user.setUserLevelId(o.getId());
                    users.add(user);
                    break;
                }
            }
        }
        userLevelDao.batchUpdateLevel(users);
    }

    public void changeId() {
        List<UserLevel> list=userLevelDao.getAll();
        if (!CollectionUtils.isEmpty(list)) {
            Map<String, String> map = new HashMap<>();
            for (UserLevel ul : list) {
                String id = ul.getId();
                if (id.length() == 11) {
                    long longId = UUIDGenerator.reverseShortUUID(id);
                    map.put(id, String.valueOf(longId));
                }
            }
            if (!CollectionUtils.isEmpty(map)) {
                userLevelDao.changeId(map);
                userDao.changeUserLevelId(map);
            }
        }
    }
}
